package com.smart.oauth2.config;

import com.smart.oauth2.service.OauthClientDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.annotation.Resource;
import java.security.KeyPair;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 开启oauth2认证服务
 * 1. 授权客服端使用持久化
 */
@Configuration
@EnableAuthorizationServer
public class OauthServerConfigAdapter extends AuthorizationServerConfigurerAdapter {
    public static final String JKS_FILE_NAME = "hello.jks";
    public static final String JKS_FILE_PASSWORD = "123456";
    public static final String JKS_ALIAS_NAME = "hello";


    /**
     * 微信支持    必须开发者中心注册开发者账号 ,注册开发者应用
     * <p>
     * 授权客服端配置
     * app   ios  android
     * admin
     * xiaochengxu
     * pc
     *
     * @param clients
     * @throws Exception
     */
    @Resource
    ClientDetailsService oauthClientDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // clientID  app   admin   小程序
        clients.withClientDetails(oauthClientDetailsService);
    }

    @Resource
    InMemoryAuthorizationCodeServices authorizationCodeServices;

    @Resource
    TokenStore tokenStore;

    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new InMemoryAuthorizationCodeServices();
    }


    //    jwt 对称加密分
    //    对称加密
    @Bean
    public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
//        return new RedisTokenStore(redisConnectionFactory);
        return new JwtTokenStore(jwtAccessTokenConverter);
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(KeyPair keyPair) {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        //如果jwt采用对称加密
//        jwtAccessTokenConverter.setSigningKey("12345");
        // 非对称加密   RSA
        jwtAccessTokenConverter.setKeyPair(keyPair);
        return jwtAccessTokenConverter;
    }

    @Bean
    public KeyPair keyPair() {
        KeyStoreKeyFactory factory = new KeyStoreKeyFactory(
                new ClassPathResource(JKS_FILE_NAME), JKS_FILE_PASSWORD.toCharArray());
        return factory.getKeyPair(
                JKS_ALIAS_NAME, JKS_FILE_PASSWORD.toCharArray());
    }

    @Resource
    private AuthorizationServerTokenServices tokenServices;


    /**
     * es
     * 分库分表
     *
     * 在微服务下  尤其是大公司 spring cloud  + security + oauth2 + jwt
     * 认证服务断点配置
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenServices(tokenServices)
                .authorizationCodeServices(authorizationCodeServices)
                .reuseRefreshTokens(true)
                .tokenStore(tokenStore);
    }

    /**
     * 令牌端点安全约束
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 允许所有人访问请求令牌
        //允许所有人请求令牌
        security.tokenKeyAccess("permitAll()")
                //已验证的客户端才能请求check_token端点
                .checkTokenAccess("isAuthenticated()")
                .allowFormAuthenticationForClients();
    }

    /**
     * token的配置信息
     *
     * @return 令牌的过期时间
     */
    @Bean
    public DefaultTokenServices defaultTokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        //设置token持久化
        defaultTokenServices.setTokenStore(tokenStore);
        // 设置有效期
        defaultTokenServices.setAccessTokenValiditySeconds(60 * 60 * 24);
        // 刷新令牌的 时间
        defaultTokenServices.setRefreshTokenValiditySeconds(60 * 60 * 12);
        //每次获取令牌都会把刷新的令牌放入返回值中
        defaultTokenServices.setReuseRefreshToken(true);
        defaultTokenServices.setClientDetailsService(oauthClientDetailsService);
        // token加强器
//        defaultTokenServices.setTokenEnhancer();

        return defaultTokenServices;

    }

//  token的校验     网关    需要秘钥
//    提供获取秘钥的接口

}
